﻿using HY.Model;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using WebApi.Helpers;
using WebApi.Model;

namespace WebApi.Controllers
{
    /// <summary>
    /// 称重数据处理
    /// </summary>
    public class WeighController : BaseController
    {
        private readonly WeighService service;
        private readonly IConfiguration configuration;

        public WeighController(ILogger<WeighController> logger, WeighService _service, IConfiguration _configuration) : base(logger)
        {
            service = _service;
            configuration = _configuration;
        }

        [AllowAnonymous]
        [HttpPost("Query")]
        public ReturnModel Query(string guid, int complete = 0)
        {
            try
            {
                logger.LogInformation($"Weigh/Query:{guid}");
                var weightRecord = DbHelper.GetDbConn().Queryable<WeightRecord>().Where(it => it.Guid.Equals(guid) && it.IsComplete == complete).OrderBy(it => it.UpdateTime, OrderByType.Desc).First();
                ReturnModel returnModel = new ReturnModel();
                returnModel.Message = "成功";
                if (weightRecord != null)
                {
                    returnModel.Count = 1;
                    returnModel.Data = weightRecord;
                }
                return returnModel;
            }
            catch (Exception ex)
            {
                return logger.ErrorModel("称重数据Query", ex);
            }
        }

        [AllowAnonymous]
        [HttpPost("GetNewRecordId")]
        public ReturnModel GetNewRecordId(string code)
        {
            logger.LogInformation($"Weigh/GetNewRecordId:{code}");
            var exp = Expressionable.Create<WeightRecord>();
            exp.And(
                it => SqlFunc.Between(it.CreateTime, DateTime.Now.Date,
                    DateTime.Now.AddDays(1).Date));
            //exp.And(it => it.ScaleCode.Equals(code));
            exp.And(it => it.RecordId.StartsWith(code));
            var theDayLastRecord = DbHelper.GetDbConn().Queryable<WeightRecord>().Where(exp.ToExpression()).OrderBy(it => it.Id, OrderByType.Desc).First();
            string idNum = string.Empty;
            if (theDayLastRecord != null)
            {
                var id = theDayLastRecord.RecordId;
                var substring = id.Substring(id.Length - 4, 4);
                if (int.TryParse(substring, out var index))
                {
                    logger.LogInformation($"查询当前数据库最新的id,id为{id},解析的数字为{index}");
                    idNum = code + "#" + DateTime.Now.ToString("yyMMdd") + (index + 1).ToString().PadLeft(4, '0');
                }
                else
                {
                    logger.LogInformation($"查询当前数据库最新的id,id为{id},没有解析出来数字");
                    idNum = code + "#" + DateTime.Now.ToString("yyMMdd");
                }
            }
            else
            {
                logger.LogDebug($"查询当前数据库最新的id,没有查到数据");
                idNum = code + "#" + DateTime.Now.ToString("yyMMdd") + 1.ToString().PadLeft(4, '0');
            }
            logger.LogInformation($"idNum={idNum}");
            return new ReturnModel()
            {
                Count = 0,
                Code = 200,
                Message = "成功",
                Data = idNum
            };
        }

        /// <summary>
        /// 获取数据称重列表
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost("GetList")]
        public async Task<ReturnModel> GetList(QueryWeighVM model)
        {
            try
            {
                Expression<Func<WeighInfoVM, bool>> filter = e => true;
                if (!string.IsNullOrEmpty(model.TruckNum))
                    filter = filter.And(c => c.TruckNum.Contains(model.TruckNum));
                if (!string.IsNullOrEmpty(model.GoodsName))
                    filter = filter.And(c => c.GoodsName.Contains(model.GoodsName));
                if (model.IsComplete != null)
                    filter = filter.And(c => c.IsComplete == model.IsComplete.Value);
                if (model.BeginTime != null)
                    filter = filter.And(c => c.CreateTime > model.BeginTime);
                if (model.EndTime != null)
                    filter = filter.And(c => c.CreateTime < model.EndTime.Value.AddDays(1));
                if (!string.IsNullOrWhiteSpace(model.ScaleCode))
                {
                    Expression<Func<WeighInfoVM, bool>> orFilter = e => false;
                    foreach (string s in model.ScaleCode.Split('|'))
                    {
                        if (!string.IsNullOrWhiteSpace(s))
                            orFilter = orFilter.Or(c => c.ScaleCode == s);
                    }
                    filter = filter.And(orFilter);
                }
                SqlSugar.RefAsync<int> totalCount = 0;
                var data = await service.GetPageListAsync(filter, model.PageIndex, model.PageSize, totalCount);
                return new ReturnModel { Count = totalCount, Data = data };
            }
            catch (Exception ex)
            {
                return logger.ErrorModel($"{nameof(WeighController)}/{nameof(GetList)}", ex);
            }
        }

        /// <summary>
        /// 30吨汽车衡数据上传，model中Guid字段存储的是30吨汽车衡中的RFID卡号，仅用于关联对应的图片
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        /// TODO 需要增加数据上传至赤峰项目客户接口的代码
        [AllowAnonymous]
        [HttpPost("ThirtyUpdate")]
        public ReturnModel ThirtyUpdate(WeightRecord model)
        {
            logger.LogInformation($"Weigh/ThirtyUpdate:{JsonConvert.SerializeObject(model)}");
            ReturnModel returnModel = new ReturnModel();
            string opeType = "新增";
            string opeResult = "成功";
            try
            {
                int i = 0;
                using (var db = DbHelper.GetDbConn())
                {
                    if (db.Queryable<WeightRecord>().Any(it => it.RecordId.Equals(model.RecordId)))
                    {
                        opeType = "修改";
                        model.UpdateTime = model.GrossTime > model.TareTime ? model.GrossTime : model.TareTime;
                        i = db.Updateable(model).WhereColumns(it => new { it.RecordId }).ExecuteCommand();
                    }
                    else
                    {
                        model.UpdateTime = model.CreateTime;
                        i = db.Insertable(model).ExecuteCommand();
                    }

                    if (i == 0)
                    {
                        returnModel.Code = 201;
                        returnModel.Message = "受影响的行为0";
                        returnModel.Count = i;
                    }
                    else
                    {
                        returnModel.Code = 200;
                        returnModel.Message = "成功";
                        returnModel.Count = i;
                    }
                }
            }
            catch (Exception e)
            {
                opeResult = "异常";
                logger.LogError("30吨汽车衡上传数据出错。", e);
                returnModel.Code = 400;
                returnModel.Message = $"上传失败,{e.Message}";
                returnModel.Count = 0;
            }
            LogToDB("WeightRecord", opeType, JsonConvert.SerializeObject(model), opeResult, nameof(ThirtyUpdate) + returnModel.Message);
            return returnModel;
        }

        /// <summary>
        /// 正常称重数据保存（汽车衡默认第一次称重存皮重，第二次称重后根据重量调整皮重毛重值）
        /// </summary>
        /// <param name="model">称重数据</param>
        /// <returns></returns>
        [HttpPost("Save")]
        public async Task<ReturnModel> Save(WeightRecord model)
        {
            //Predefined3汽车衡类型：0（普通汽车衡），1（硫酸），2（铜粉磅:包括铜粉和多种货物；铜粉磅需要监磅，接口保存数据时需要更新监磅表），3（阴极铜）
            string opeType = "新增";
            string log = string.Empty;
            //decimal price = 0m;
            try
            {
                logger.LogInformation($"Weigh/{nameof(Save)}:{JsonConvert.SerializeObject(model)}");
                model.UpdateTime ??= DateTime.Now;
                if (model.IsComplete == 0)
                {
                    //保存称重数据
                    model.UserId1 = UserId;
                    //if (model.Predefined3 == "2")
                    //{
                    //    using var tran = DbHelper.GetDbConn().UseTran();
                    //    result.Count = await DbHelper.WeightRecord.InsertAsync(model) ? 1 : 0;
                    //    //更新监磅表
                    //    result.Count += DbHelper.GetDbConn().Updateable<Monitor>().SetColumns(it => it.Flag == 1).Where(it => it.Id == int.Parse(model.Predefined15)).ExecuteCommand();
                    //    tran.CommitTran();
                    //}
                    //else
                    result.Count = await DbHelper.WeightRecord.InsertAsync(model) ? 1 : 0;
                }
                else
                {
                    opeType = "修改";
                    model.UserId2 = UserId;
                    //第二次后台人员取的重量存到毛重，如顺序不正确，则在显示时调换显示
                    //if (model.SuperviseGrossWeight < model.SuperviseTareWeight)
                    //    (model.SuperviseGrossWeight, model.SuperviseTareWeight) = (model.SuperviseTareWeight, model.SuperviseGrossWeight);

                    //某些净重较轻时不需要计算净重的货物判断
                    if (configuration.GetValue("WeighParams:NotSaveGoods", "").Split('|').Contains(model.GoodsName) && configuration.GetValue("WeighParams:NotSaveWeight", 0) > model.NetWeight)
                    {
                        //净重置为0，完成称重，方便还卡出厂
                        model.NetWeight = 0;
                    }

                    #region 硫酸

                    //GPutOnRecord grecord = null;
                    //YPutOnRecord yrecord = null;
                    //if (configuration.GetValue("WeighParams:H2SO4_925", "") == model.GoodsName || configuration.GetValue("WeighParams:H2SO4_98", "") == model.GoodsName || configuration.GetValue("WeighParams:H2SO4_1045", "") == model.GoodsName)
                    //{
                    //    model.Predefined3 = "1";
                    //    grecord = await DbHelper.GPutOnRecord.GetFirstAsync(it => it.GNumber == SqlFunc.Subqueryable<RegisterInfo>().Where(s => s.Guid == model.Guid).Select(s => s.Value6));
                    //    if (grecord == null)
                    //    {
                    //        result.Message = "未获取到硫酸购买备案信息";
                    //        return logger.Code_202($"{model.RecordId}:{result.Message}");
                    //    }
                    //    //下面判断及更新剩余量
                    //    if (!grecord.InCity)
                    //    {
                    //        yrecord = await DbHelper.YPutOnRecord.GetFirstAsync(it => it.YNumber == SqlFunc.Subqueryable<RegisterInfo>().Where(s => s.Guid == model.Guid).Select(s => s.YNumber));
                    //        if (yrecord == null)
                    //        {
                    //            result.Message = "未获取到硫酸运输备案信息";
                    //            return logger.Code_202($"{model.RecordId}:{result.Message}");
                    //        }
                    //        else if (yrecord.RemainingWeight < model.NetWeight)
                    //        {
                    //            result.Message = "运输备案信息剩余硫酸量不足";
                    //            return logger.Code_202($"{model.RecordId}:{result.Message}");
                    //        }
                    //        yrecord.RemainingWeight -= (int)model.NetWeight;
                    //    }
                    //    else if (grecord.RemainingWeight < model.NetWeight)
                    //    {
                    //        result.Message = "购买备案信息剩余硫酸量不足";
                    //        return logger.Code_202($"{model.RecordId}:{result.Message}");
                    //    }
                    //    //无论市内市外，都需要减购买备案号剩余量
                    //    grecord.RemainingWeight -= (int)model.NetWeight;

                    //    //下面处理剩余金额
                    //    if (configuration.GetValue("WeighParams:H2SO4_925", "") == model.GoodsName && grecord.Enable925)
                    //        price = grecord.Price925 ?? 0m;
                    //    else if (configuration.GetValue("WeighParams:H2SO4_98", "") == model.GoodsName && grecord.Enable98)
                    //        price = grecord.Price98 ?? 0m;
                    //    else if (configuration.GetValue("WeighParams:H2SO4_1045", "") == model.GoodsName && grecord.Enable1045)
                    //        price = grecord.Price1045 ?? 0m;
                    //    if (price != 0m)
                    //    {
                    //        if (model.NetWeight * price > grecord.GBalance && (grecord.EnableCheck ?? false))
                    //        {
                    //            result.Message = "收货单位账户余额不足";
                    //            return logger.Code_202($"{model.RecordId}:{result.Message}");
                    //        }
                    //        grecord.GBalance -= model.NetWeight * price;
                    //    }
                    //}

                    #endregion 硫酸

                    //using (var tran = DbHelper.GetDbConn().UseTran())
                    //{
                    //if (model.Predefined3 == "2")
                    //{
                    //    //更新监磅表
                    //    result.Count += DbHelper.GetDbConn().Updateable<Monitor>().SetColumns(it => new Monitor { Flag = 2 }).Where(it => it.Id == int.Parse(model.Predefined15)).ExecuteCommand();
                    //}
                    //else if (model.Predefined3 == "1")
                    //{
                    //    DbHelper.GPutOnRecord.Update(grecord);
                    //    if (yrecord != null)
                    //        DbHelper.YPutOnRecord.Update(yrecord);
                    //    result.Count += await DbHelper.YRecord.InsertAsync(new YRecord { CreateTime = DateTime.Now, GNumber = grecord.GNumber, GCompany = grecord.GCompany, GoodsName = model.GoodsName, YCompany = yrecord?.YCompany, Plate = model.TruckNum, RecordId = model.RecordId, RemainingWeight = grecord.RemainingWeight, TransTime = model.UpdateTime, Weight = (int)(model.NetWeight ?? 0m), YNumber = yrecord?.YNumber, Price = price }) ? 1 : 0;
                    //}
                    if (!DbHelper.WeightRecord.IsAny(it => it.RecordId == model.RecordId))
                    {
                        opeType = "新增";
                        result.Count = await DbHelper.WeightRecord.InsertAsync(model) ? 1 : 0;
                    }
                    else//需记得排除掉不需要更新的字段
                        result.Count = await DbHelper.GetDbConn().Updateable(model).IgnoreColumns(it => new { it.UserId1, it.SuperviseTareWeight, it.CreateTime, it.UpdateState, it.GuFeiUploadState }).WhereColumns(it => new { it.RecordId, it.Guid }).ExecuteCommandAsync();
                    //tran.CommitTran();
                    //}
                }
                LogToDB("WeightRecord", opeType, JsonConvert.SerializeObject(model), "成功", $"影响条数{result.Count}，{log}");
                return result;
            }
            catch (Exception ex)
            {
                LogToDB("WeightRecord", opeType, JsonConvert.SerializeObject(model), "异常", ex.Message);
                return logger.ErrorModel($"{nameof(WeighController)}/{nameof(Save)}", ex);
            }
        }

        /// <summary>
        /// 获取集控首页数据称重列表
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost("TopList")]
        public async Task<ReturnModel> TopList(QueryWeighVM model)
        {
            try
            {
                Expression<Func<WeightRecord, bool>> filter = e => true;
                if (model.IsMoHu)
                {
                    if (!string.IsNullOrEmpty(model.TruckNum))
                        filter = filter.And(c => c.TruckNum.Contains(model.TruckNum));
                    if (!string.IsNullOrEmpty(model.GoodsName))
                        filter = filter.And(c => c.GoodsName.Contains(model.GoodsName));
                }
                else
                {
                    if (!string.IsNullOrEmpty(model.TruckNum))
                        filter = filter.And(c => c.TruckNum == model.TruckNum);
                    if (!string.IsNullOrEmpty(model.GoodsName))
                        filter = filter.And(c => c.GoodsName == model.GoodsName);
                }
                if (model.BeginTime != null)
                    filter = filter.And(c => c.CreateTime > model.BeginTime);
                if (model.EndTime != null)
                    filter = filter.And(c => c.CreateTime < model.EndTime.Value.AddDays(1));
                if (model.IsComplete != null)
                    filter = filter.And(c => c.IsComplete == model.IsComplete.Value);
                if (!string.IsNullOrWhiteSpace(model.ScaleCode))
                {
                    Expression<Func<WeightRecord, bool>> orFilter = e => false;
                    foreach (string s in model.ScaleCode.Split('|'))
                    {
                        if (!string.IsNullOrWhiteSpace(s))
                            orFilter = orFilter.Or(c => c.ScaleCode == s);
                    }
                    filter = filter.And(orFilter);
                }
                var data = await DbHelper.GetDbConn().Queryable<WeightRecord>().Where(filter).OrderBy(o => o.UpdateTime, OrderByType.Desc).Take(model.Top).ToListAsync();
                return new ReturnModel { Count = data.Count, Data = data };
            }
            catch (Exception ex)
            {
                return logger.ErrorModel($"{nameof(WeighController)}/{nameof(TopList)}", ex);
            }
        }

        /// <summary>
        /// 更新称重数据
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost("Update")]
        public async Task<ReturnModel> Update(WeightRecord model)
        {
            try
            {
                result.Count = await DbHelper.GetDbConn().Updateable(model).UpdateColumns(it => new { it.SendCptName, it.GoodsName, it.ReceiveCptName }).ExecuteCommandAsync();
                LogToDB("WeightRecord", "更新", JsonConvert.SerializeObject(new { RecordId = model.RecordId, SendCptName = model.SendCptName, ReceiveCptName = model.ReceiveCptName, GoodsName = model.GoodsName }), "成功");
                return result;
            }
            catch (Exception ex)
            {
                LogToDB("WeightRecord", "更新", JsonConvert.SerializeObject(new { RecordId = model.RecordId, SendCptName = model.SendCptName, ReceiveCptName = model.ReceiveCptName, GoodsName = model.GoodsName }), "异常", ex.Message);
                return logger.ErrorModel($"{nameof(WeighController)}/{nameof(Update)}", ex);
            }
        }

        /// <summary>
        /// 获取未上传到检化线系统的数据列表
        /// </summary>
        /// <returns></returns>
        [HttpPost("NoUploadList")]
        public async Task<ReturnModel> NoUploadList([FromForm] string scaleCodes)
        {
            try
            {
                //半条数据未上传时都是0，上传后UpdateState变为1，整条数据后IsComplete变为1，此时相等再次上传UpdateState变为2
                Expression<Func<WeightRecord, bool>> filter = it => it.UpdateState <= it.IsComplete;
                if (!string.IsNullOrWhiteSpace(scaleCodes))
                {
                    Expression<Func<WeightRecord, bool>> orFilter = e => false;
                    foreach (string s in scaleCodes.Split('|'))
                    {
                        if (!string.IsNullOrWhiteSpace(s))
                            orFilter = orFilter.Or(c => c.ScaleCode == s);
                    }
                    filter = filter.And(orFilter);
                }
                List<WeightRecord> data = await DbHelper.WeightRecord.GetListAsync(filter);
                return new ReturnModel { Count = data.Count, Data = data };
            }
            catch (Exception ex)
            {
                return logger.ErrorModel(nameof(NoUploadList), ex);
            }
        }

        /// <summary>
        /// 更新上传状态
        /// </summary>
        /// <param name="RecordId">称重记录编号</param>
        /// <param name="UpdateState">上传状态0未上传1上传半条2上传一条</param>
        /// <returns></returns>
        [HttpPost("UpdateUploadState")]
        public async Task<ReturnModel> UpdateUploadState([FromForm] string RecordId, [FromForm] int UpdateState)
        {
            try
            {
                logger.LogInformation($"Weigh/UpdateUploadState:RecordId={RecordId},UpdateState={UpdateState}");
                result.Count = await DbHelper.GetDbConn().Updateable<WeightRecord>().SetColumns(it => it.UpdateState == UpdateState).Where(it => it.RecordId == RecordId).ExecuteCommandAsync();
                LogToDB("WeightRecord", "更新", JsonConvert.SerializeObject(new { RecordId = RecordId, UpdateState = UpdateState }), "成功");
                return result;
            }
            catch (Exception ex)
            {
                LogToDB("WeightRecord", "更新", JsonConvert.SerializeObject(new { RecordId = RecordId, UpdateState = UpdateState }), "异常", ex.Message);
                return logger.ErrorModel($"{nameof(WeighController)}/{nameof(UpdateUploadState)}", ex);
            }
        }

        /// <summary>
        /// 获取未上传到固废系统的数据列表
        /// </summary>
        /// <returns></returns>
        [HttpPost("NoUploadListGuFei")]
        public async Task<ReturnModel> NoUploadListGuFei([FromForm] string scaleCodes)
        {
            try
            {
                //只上传称重完成的数据
                Expression<Func<WeightRecord, bool>> filter = it => it.IsComplete == 1 && it.GuFeiUploadState == 0;
                if (!string.IsNullOrWhiteSpace(scaleCodes))
                {
                    Expression<Func<WeightRecord, bool>> orFilter = e => false;
                    foreach (string s in scaleCodes.Split('|'))
                    {
                        if (!string.IsNullOrWhiteSpace(s))
                            orFilter = orFilter.Or(c => c.ScaleCode == s);
                    }
                    filter = filter.And(orFilter);
                }
                List<WeightRecord> data = await DbHelper.WeightRecord.GetListAsync(filter);
                return new ReturnModel { Count = data.Count, Data = data };
            }
            catch (Exception ex)
            {
                return logger.ErrorModel(nameof(NoUploadListGuFei), ex);
            }
        }

        /// <summary>
        /// 更新固废上传状态
        /// </summary>
        /// <param name="RecordId">称重记录编号</param>
        /// <param name="UpdateState">上传状态0未上传1上传半条2上传一条</param>
        /// <returns></returns>
        [HttpPost("UpdateUploadStateGuFei")]
        public async Task<ReturnModel> UpdateUploadStateGuFei([FromForm] string RecordId, [FromForm] int UpdateState)
        {
            try
            {
                logger.LogInformation($"Weigh/UpdateUploadStateGuFei:RecordId={RecordId},UpdateState={UpdateState}");
                result.Count = await DbHelper.GetDbConn().Updateable<WeightRecord>().SetColumns(it => it.GuFeiUploadState == UpdateState).Where(it => it.RecordId == RecordId).ExecuteCommandAsync();
                LogToDB("WeightRecord", "更新", JsonConvert.SerializeObject(new { RecordId = RecordId, GuFeiUploadState = UpdateState }), "成功");
                return result;
            }
            catch (Exception ex)
            {
                LogToDB("WeightRecord", "更新", JsonConvert.SerializeObject(new { RecordId = RecordId, GuFeiUploadState = UpdateState }), "异常", ex.Message);
                return logger.ErrorModel($"{nameof(WeighController)}/{nameof(UpdateUploadState)}", ex);
            }
        }

        /// <summary>
        /// 查询当天指定车牌号已完成称重流程的最大编号
        /// </summary>
        /// <param name="plate"></param>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpPost("QueryDayCount")]
        public ReturnModel QueryDayCount(string plate)
        {
            try
            {
                logger.LogInformation($"Weigh/QueryDayCount:{plate}");
                var weightRecord = DbHelper.GetDbConn().Queryable<WeightRecord>().OrderBy(it => it.Id, OrderByType.Desc).First(it => it.TruckNum.StartsWith(plate) && it.IsComplete == 1 && SqlFunc.DateIsSame(it.CreateTime, DateTime.Today));
                ReturnModel returnModel = new ReturnModel();
                returnModel.Message = "成功";
                if (weightRecord != null)
                {
                    returnModel.Count = weightRecord.TruckNum.Contains("-") ? int.Parse(weightRecord.TruckNum.Split('-')[1]) : 1;
                }
                logger.LogInformation($"Weigh/QueryDayCount:plate={plate},return={JsonConvert.SerializeObject(returnModel)}");
                return returnModel;
            }
            catch (Exception ex)
            {
                return logger.ErrorModel("Weigh/QueryDayCount", ex);
            }
        }
    }
}